const randomColor = () => {
	const random = () => Math.floor(Math.random() * 200 + 55);
	return `rgb( ${random()}, ${random()}, ${random()})`;
};
export class GridLayer {
	ctx = null; //canvas上下文
	rowNum = 0; //网格行数
	colNum = 0; //网格列数
	width = 0; // 画布宽度
	height = 0; //画布高度
	cellWidth = 0; //单元格宽度
	cellHeight = 0; //单元格高度
	cellsData = []; //单元格数据
	config = {}; //区域/显示索引等配置
	removeAreaInitial = false; //移除区域事件是否初始化
	isChooseArea = false; // 正在选择区域事件标识
	areaChooseInitialized = false; // 区域选择是否初始化
	constructor(ele, rowNum, colNum, config) {
		if (!ele.clientWidth || !ele.clientHeight) {
			console.log('canvas has no height or width!');
			return this;
		}
		this.ele = ele;
		this.ctx = ele.getContext('2d');
		return this.init(rowNum, colNum, config);
	}

	init(rowNum, colNum, config) {
		this.initConfig(rowNum, colNum, config);
		this.render();
		window.addEventListener('resize', () => {
			this.resize();
		});
		return this;
	}

	initConfig(rowNum, colNum, config) {
		//初始化配置
		this.config = config || this.config || {};
		this.rowNum = rowNum;
		this.colNum = colNum;
	}

	update(...args) {
		//更新 元素/行/列数
		this.initConfig(...args);
		this.render();
	}

	render() {
		this.getSize(); //重新获取宽高/单元格大小等
		this.reset(); //重置画布
		this.drawGrid();
		if (this.config.areas) {
			this.drawAreas();
		}
	}

	reset() {
		//重置画布
		this.ctx.clearRect(0, 0, this.width, this.height);
	}

	getSize() {
		this.width = this.ele.clientWidth;
		this.height = this.ele.clientHeight;

		this.ele.setAttribute('width', this.width);
		this.ele.setAttribute('height', this.height);
		//	单元格元素宽高
		this.cellWidth = `${this.width / this.colNum}`.substr(0, 5) - 0;
		this.cellHeight = `${this.height / this.rowNum}`.substr(0, 5) - 0;
		//	单元格数组
		this.cellsData = [];
		this.initCells();
	}

	resize() {
		//resize 再次渲染
		this.getSize();
		this.render();
	}

	initCells() {
		//	初始化单元格
		for (let ri = 0; ri < this.rowNum; ri++) {
			const rowCells = [];
			for (let ci = 0; ci < this.colNum; ci++) {
				//	记录单元格起始及结束坐标
				const cell = {
					start: [this.cellWidth * ci, this.cellHeight * ri],
					end: [this.cellWidth * (ci + 1), this.cellHeight * (ri + 1)],
				};
				rowCells.push(cell);
			}
			this.cellsData.push(rowCells);
		}
	}

	drawGrid() {
		//绘制网格
		this.ctx.save();
		this.ctx.strokeStyle = '#333';
		this.ctx.lineWidth = 1;
		this.ctx.shadowColor = undefined;
		this.ctx.shadowOffsetX = 0;
		this.ctx.shadowOffsetY = 0;
		//绘制横线
		for (let ri = 1; ri < this.cellsData.length; ri++) {
			const row = this.cellsData[ri];
			this.ctx.beginPath();
			this.ctx.moveTo(0, row[0].start[1]);
			this.ctx.lineTo(this.width, row[0].start[1]);
			this.ctx.stroke();
		}
		//绘制竖线
		const row1 = this.cellsData[0];
		for (let ci = 1; ci < row1.length; ci++) {
			const col = row1[ci];
			this.ctx.beginPath();
			this.ctx.moveTo(col.start[0], 0);
			this.ctx.lineTo(col.start[0], this.height);
			this.ctx.stroke();
		}
		this.ctx.strokeRect(0, 0, this.width, this.height);
		if (this.config.showIndex) {
			this.drawIndex();
		}
		this.ctx.restore();
	}

	drawIndex() {
		//绘制单元格序号
		this.ctx.save();
		this.ctx.strokeStyle = '#333';
		this.ctx.lineWidth = 0.5;
		this.ctx.shadowColor = undefined;
		this.ctx.shadowOffsetX = 0;
		this.ctx.shadowOffsetY = 0;
		for (let ri = 0; ri < this.cellsData.length; ri++) {
			const row = this.cellsData[ri];
			for (let ci = 0; ci < row.length; ci++) {
				const cell = row[ci];
				if (this.config.showIndex) {
					//绘制行-列
					this.ctx.font = '14px serif';
					this.ctx.strokeStyle = '#333';
					this.ctx.strokeText(`${ri + 1}-${ci + 1}`, cell.start[0] + 8, cell.start[1] + 15);
				}
			}
		}
		this.ctx.restore();
	}

	drawAreas() {
		const walkArea = (cb) => {
			//遍历区域
			for (let i = 0; i < this.config.areas.length; i++) {
				const areaItem = this.config.areas[i];
				const position = areaItem.coordinate;
				const startX = (position[1] - 1) * this.cellWidth;
				const startY = (position[0] - 1) * this.cellHeight;
				const width = (position[3] - position[1]) * this.cellWidth;
				const height = (position[2] - position[0]) * this.cellHeight;
				cb(areaItem, startX, startY, width, height);
			}
		};
		const drawAreaItem = (areaItem, startX, startY, width, height) => {
			//绘制单个区域及删除按钮
			this.ctx.fillStyle = areaItem.bgColor;
			this.ctx.fillRect(startX, startY, width, height);
			if (!areaItem.disabled) {
				this.ctx.font = '20px serif';
				this.ctx.strokeStyle = areaItem.closeHover ? '#fff' : '#000';
				this.ctx.strokeText('×', startX + width - 20, startY + 20);
			}
		};
		if (!this.removeAreaInitial) {
			this.ele.addEventListener('mousemove', (e) => {
				if (this.isChooseArea) {
					return;
				}
				walkArea((areaItem, startX, startY, width, height) => {
					const closeHover = areaItem.closeHover;
					areaItem.closeHover =
						e.offsetX > startX + width - 20 &&
						e.offsetX < startX + width &&
						e.offsetY > startY &&
						e.offsetY < startY + 20;
					if (closeHover !== !!areaItem.closeHover) {
						drawAreaItem(areaItem, startX, startY, width, height);
					}
				});
			});
			this.ele.addEventListener('click', (e) => {
				if (this.isChooseArea) {
					return;
				}
				walkArea((areaItem, startX, startY, width, height) => {
					const closeHover =
						e.offsetX > startX + width - 20 &&
						e.offsetX < startX + width &&
						e.offsetY > startY &&
						e.offsetY < startY + 20;
					if (!this.isChooseArea && closeHover) {
						this.config.onDeleteArea(areaItem);
					}
				});
			});
			this.removeAreaInitial = true;
		}
		walkArea((...args) => {
			drawAreaItem(...args);
		});
	}

	initSelector(onChange, onSelected) {
		let x, y;
		this.ele.addEventListener('mousemove', (e) => {
			this.reset(); //	重置画布
			this.drawGrid();
			this.ctx.fillStyle = 'rgba(150, 150, 150, 0.3)';
			//	绘制选中区域
			this.ctx.fillRect(0, 0, e.offsetX, e.offsetY);

			x = Math.ceil(e.offsetX / this.cellWidth);
			y = Math.ceil(e.offsetY / this.cellHeight);
			onChange && onChange(x, y);
		});
		this.ele.addEventListener('click', (e) => {
			onSelected && onSelected(x, y, e);
		});
	}

	startAreaSelect(cb, onAreaDuplicate, onAreaOverLap) {
		this.ele.style.cursor = 'crosshair';
		//初始化区域
		let startX, startY, startColIndex, startRowIndex, endColIndex, endRowIndex, bgColor;
		let beginChoose = false;
		this.isChooseArea = true;
		if (!this.areaChooseInitialized) {
			const isAreaOverLap = (area1, area2) => {
				//检测坐标轴内矩形是否重叠 coordinate: [[x1, y1], [x2, y2]]
				const p1StartX = area1[0][0];
				const p1StartY = area1[0][1];
				const p1EndX = area1[1][0];
				const p1EndY = area1[1][1];
				const p2StartX = area2[0][0];
				const p2StartY = area2[0][1];
				const p2EndX = area2[1][0];
				const p2EndY = area2[1][1];
				const minx = Math.max(p1StartX, p2StartX);
				const miny = Math.max(p1StartY, p2StartY);
				const maxx = Math.min(p1EndX, p2EndX);
				const maxy = Math.min(p1EndY, p2EndY);
				return !(minx >= maxx || miny >= maxy); //true 重叠
			};
			const hasOverLapArea = (addArea) => {
				//判断区域是否重叠
				let flag = false;
				const { areas = [] } = this.config;
				for (let i = 0; i < areas.length; i++) {
					const { coordinate } = areas[i];
					if (coordinate) {
						flag = isAreaOverLap(addArea, [
							[coordinate[1] - 1, coordinate[0] - 1],
							[coordinate[3] - 1, coordinate[2] - 1],
						]);
						if (flag) {
							return flag;
						}
					}
				}
				return flag;
			};
			const endChoose = (e) => {
				beginChoose = false;
				if (!endColIndex || !endRowIndex) {
					//点击了未框选
					return;
				}
				if (
					!hasOverLapArea([
						[startColIndex, startRowIndex],
						[endColIndex, endRowIndex],
					])
				) {
					cb(startColIndex, startRowIndex, endColIndex, endRowIndex, bgColor);
				} else {
					onAreaOverLap(startColIndex, startRowIndex, endColIndex, endRowIndex);
				}
			};

			const checkDuplicate = (e) => {
				let flag = false;
				const { areas = [] } = this.config;
				for (let i = 0; i < areas.length; i++) {
					const { coordinate } = areas[i];
					if (coordinate) {
						const startX = (coordinate[1] - 1) * this.cellWidth;
						const startY = (coordinate[0] - 1) * this.cellHeight;
						const endX = (coordinate[3] - 1) * this.cellWidth;
						const endY = (coordinate[2] - 1) * this.cellHeight;
						flag = e.offsetX >= startX && e.offsetX <= endX && e.offsetY >= startY && e.offsetY <= endY;
						if (flag) {
							return flag;
						}
					}
				}
				return flag;
			};

			this.ele.addEventListener('mousedown', (e) => {
				// 按下鼠标开始选择
				if (!this.isChooseArea) {
					return;
				}
				if (!beginChoose) {
					//记录起始坐标
					startX = e.offsetX;
					startY = e.offsetY;
					startColIndex = Math.floor(startX / this.cellWidth);
					startRowIndex = Math.floor(startY / this.cellHeight);
					bgColor = randomColor();
					if (checkDuplicate(e)) {
						//检查是否区域已被使用
						onAreaDuplicate(e, startRowIndex + 1, startColIndex + 1);
						return;
					}
					beginChoose = true;
				}
			});
			this.ele.addEventListener('mousemove', (e) => {
				if (beginChoose) {
					this.render();
					this.ctx.fillStyle = bgColor;
					let paintStartX, paintStartY, width, height;
					//根据移动行为绘制
					if (e.offsetX > startX && e.offsetY > startY) {
						//坐标轴右下拉取
						startColIndex = Math.floor(startX / this.cellWidth);
						startRowIndex = Math.floor(startY / this.cellHeight);
						endColIndex = Math.ceil(e.offsetX / this.cellWidth);
						endRowIndex = Math.ceil(e.offsetY / this.cellHeight);
						paintStartX = startColIndex * this.cellWidth;
						paintStartY = startRowIndex * this.cellHeight;
						width = e.offsetX - paintStartX;
						height = e.offsetY - paintStartY;
					}
					if (e.offsetX > startX && e.offsetY < startY) {
						//坐标轴右上拉取
						startColIndex = Math.floor(startX / this.cellWidth);
						startRowIndex = Math.floor(e.offsetY / this.cellHeight);
						endColIndex = Math.ceil(e.offsetX / this.cellWidth);
						endRowIndex = Math.ceil(startY / this.cellHeight);
						paintStartX = startColIndex * this.cellWidth;
						paintStartY = e.offsetY;
						width = e.offsetX - paintStartX;
						height = endRowIndex * this.cellHeight - e.offsetY;
					}
					if (e.offsetX < startX && e.offsetY > startY) {
						//坐标轴左下拉取
						startColIndex = Math.floor(e.offsetX / this.cellWidth);
						startRowIndex = Math.floor(startY / this.cellHeight);
						endColIndex = Math.ceil(startX / this.cellWidth);
						endRowIndex = Math.ceil(e.offsetY / this.cellHeight);
						paintStartX = e.offsetX;
						paintStartY = startRowIndex * this.cellHeight;
						width = endColIndex * this.cellWidth - e.offsetX;
						height = e.offsetY - startRowIndex * this.cellHeight;
					}
					if (e.offsetX < startX && e.offsetY < startY) {
						//坐标轴左上拉取
						startColIndex = Math.floor(e.offsetX / this.cellWidth);
						startRowIndex = Math.floor(e.offsetY / this.cellHeight);
						endColIndex = Math.ceil(startX / this.cellWidth);
						endRowIndex = Math.ceil(startY / this.cellHeight);
						paintStartX = e.offsetX;
						paintStartY = e.offsetY;
						width = endColIndex * this.cellWidth - e.offsetX;
						height = endRowIndex * this.cellHeight - e.offsetY;
					}
					//绘制选中区域
					console.log('绘制选中区域')
					this.ctx.fillRect(paintStartX, paintStartY, width, height);
				}
			});
			this.ele.addEventListener('mouseup', (e) => {
				// 松开鼠标结束选择
				if (beginChoose) {
					endChoose(e);
				}
			});

			this.ele.addEventListener('mouseleave', (e) => {
				this.ele.style.cursor = 'auto';
				this.isChooseArea = false;
				beginChoose = false;
				this.render();
			});
			this.areaChooseInitialized = true;
		}
	}
}
